package org.example.designmodel.masterwork;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.atomic.AtomicInteger;

public class Master<T extends Task, R> {

    private Map<String, Worker<T, R>> worderMap = new HashMap<>();

    // 任务队列
    private LinkedBlockingDeque<T> queue = new LinkedBlockingDeque<>();

    protected Map<String, R> results = new ConcurrentHashMap<>();

    private Thread thread;

    private AtomicInteger sum = new AtomicInteger(0);

    public Master(int workerCount) {
        for (Integer i = 0; i < workerCount; i++) {
            Worker worker = new Worker();
            worderMap.put("节点" + i, worker);
        }
        thread = new Thread(() -> this.execute());
        thread.start();
    }

    public void submit(T t) {
        queue.add(t);
    }

    public void resultCallBack(Object o) {
        Task task = (Task) o;
        R r = (R) task.getResult();
        String taskName = "Worker:" + task.getWorkerId() + "-" + "Task:" + task.getId();
        results.put(taskName, r);
        sum.addAndGet((Integer) r);
    }

    // 调度线程
    public void execute() {
        for (; ; ) {
            Set<Map.Entry<String, Worker<T, R>>> entries = worderMap.entrySet();
            for (Map.Entry<String, Worker<T, R>> entry : entries) {
                Task task = null;
                try {
                    task = queue.take();
                    Worker worker = entry.getValue();
                    worker.submit(task, this::resultCallBack);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 打印结果
     */
    public void printResult() {
        System.out.println("sum = " + sum.get());
        Set<Map.Entry<String, R>> entries = results.entrySet();
        for (Map.Entry<String, R> entry : entries) {
            System.out.println(entry.getKey() + ":" + entry.getValue());
        }
    }

}
